package com.dingding.gmall.product.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dingding.gmall.common.constant.ProductConstant;
import com.dingding.gmall.common.dto.SpuBoundDTO;
import com.dingding.gmall.common.dto.es.SkuEsModel;
import com.dingding.gmall.common.exception.BizCodeEnum;
import com.dingding.gmall.common.exception.RRException;
import com.dingding.gmall.common.utils.PageUtils;
import com.dingding.gmall.common.utils.Query;
import com.dingding.gmall.common.utils.R;
import com.dingding.gmall.product.dao.SpuInfoDao;
import com.dingding.gmall.product.dto.SkuHasStockDTO;
import com.dingding.gmall.product.entity.*;
import com.dingding.gmall.product.feign.CouponFeignService;
import com.dingding.gmall.product.feign.SearchFeignService;
import com.dingding.gmall.product.feign.WareFeignService;
import com.dingding.gmall.product.service.*;
import com.dingding.gmall.product.vo.BaseAttrs;
import com.dingding.gmall.product.vo.Bounds;
import com.dingding.gmall.product.vo.Skus;
import com.dingding.gmall.product.vo.SpuSaveVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    private SpuInfoDescService spuInfoDescService;

    @Autowired
    private SpuImagesService spuImagesService;

    @Autowired
    private ProductAttrValueService productAttrValueService;

    @Autowired
    private SkuInfoService skuInfoService;

    @Autowired
    private CouponFeignService couponFeginService;

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private AttrService attrService;

    @Autowired
    private WareFeignService wareFeignService;

    @Autowired
    private SearchFeignService searchFeignService;

    @Override
    public void saveSpuInfo(SpuSaveVO spuSaveVo) {
        //1、 保存spu基本信息 - pms_spu_info
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(spuSaveVo, spuInfoEntity);
        spuInfoEntity.setCreateTime(new Date());
        spuInfoEntity.setUpdateTime(new Date());
        this.saveBaseSpuInfo(spuInfoEntity);

        //2、 保存spu的描述图片 - pms_spu_info_desc
        SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
        spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
        spuInfoDescEntity.setDecript(String.join(",", spuSaveVo.getDecript()));
        spuInfoDescService.saveSpuInfoDesc(spuInfoDescEntity);

        //3、 保存spu图片集 - pms_spu_images
        List<String> images = spuSaveVo.getImages();
        spuImagesService.saveImages(spuInfoEntity.getId(), images);

        //4、 保存spu的规格参数 - pms_product_attr_value
        List<BaseAttrs> baseAttrs = spuSaveVo.getBaseAttrs();
        productAttrValueService.saveProductAttrs(spuInfoEntity.getId(), baseAttrs);

        //5、 保存spu的积分信息 - gmall_sms -> sms_spu_bounds
        Bounds bounds = spuSaveVo.getBounds();
        SpuBoundDTO spuBoundDTO = new SpuBoundDTO();
        BeanUtils.copyProperties(bounds, spuBoundDTO);
        spuBoundDTO.setSpuId(spuInfoEntity.getId());
        R r = couponFeginService.saveSpuBounds(spuBoundDTO);
        if (r.getCode() != 0) {
            log.error("远程保存spu积分信息失败");
        }

        //6、 保存当前spu对应的sku信息
        // * 6.1 sku的基本信息 - pms_sku_info
        List<Skus> skus = spuSaveVo.getSkus();
        skuInfoService.saveSkuInfos(spuInfoEntity, skus);
        // * 6.2 sku的图片信息 - pms_sku_images  -------> 写到SkuInfoService
        // * 6.3 sku的销售属性信息 - pms_sku_sale_attr_value  -------> 写到SkuInfoService
        // * 6.4 sku的优惠，满减等信息 - gmall_sms -> sms_sku_ladder/sms_sku_full_reduction/sms_member_price  -------> 写到SkuInfoService

    }

    @Override
    public void saveBaseSpuInfo(SpuInfoEntity spuInfoEntity) {
        if (spuInfoEntity != null) {
            this.save(spuInfoEntity);
        }
    }

    /**
     * status
     * key
     * brandId
     * catelogId
     *
     * @param params
     * @return
     */
    @Override
    public PageUtils queryByCondition(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();
        String key = (String) params.get("key");
        if (StringUtils.isNotBlank(key)) {
            wrapper.and(index -> index.eq("id", key).or().like("spu_name", key));
        }
        String status = (String) params.get("status");
        if (StringUtils.isNotBlank(status)) {
            wrapper.eq("public_status", status);
        }
        String brandId = (String) params.get("brandId");
        if (StringUtils.isNotBlank(brandId) && !"0".equals(brandId)) {
            wrapper.eq("brand_id", brandId);
        }
        String catelogId = (String) params.get("catelogId");
        if (StringUtils.isNotBlank(catelogId) && !"0".equals(brandId)) {
            wrapper.eq("catelog_id", catelogId);
        }

        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params), wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public void up(Long spuId) {
        //1、查出当前spuId对应的sku信息，品牌名字
        List<SkuInfoEntity> skuInfoEntityList = skuInfoService.getSkuInfoBySpuId(spuId);

        //4、TODO 查询当前sku的所有可被用来检索的规格属性
        List<ProductAttrValueEntity> productAttrValueEntityList = productAttrValueService.baseAttrListForSpu(spuId);
        List<SkuEsModel.Attrs> attrList = null;
        if (!CollectionUtils.isEmpty(productAttrValueEntityList)) {
            List<Long> collect = productAttrValueEntityList.stream().map(ProductAttrValueEntity::getAttrId).collect(Collectors.toList());
            List<Long> searchAttrIdList = attrService.selectSearchAttrIds(collect);
            Set<Long> idSet = new HashSet<>(searchAttrIdList);

            attrList = productAttrValueEntityList.stream()
                    .filter(item -> idSet.contains(item.getAttrId()))
                    .map(item -> {
                        SkuEsModel.Attrs attrs = new SkuEsModel.Attrs();
                        BeanUtils.copyProperties(item, attrs);
                        return attrs;
                    })
                    .collect(Collectors.toList());

        }
        //1、TODO 发送远程调用，是否有库存
        List<Long> skuIds = skuInfoEntityList.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        Map<Long, Boolean> stockMap = null;
        try{

            R r = wareFeignService.getSkusHasStock(skuIds);


            TypeReference<List<SkuHasStockDTO>> typeReference = new TypeReference<List<SkuHasStockDTO>>(){};
            List<SkuHasStockDTO> list = r.getData("data",  typeReference);
            if (!CollectionUtils.isEmpty(list)){
                stockMap = list.stream().collect(Collectors.toMap(SkuHasStockDTO::getSkuId, SkuHasStockDTO::getHasStock));
            }
        }catch (Exception e) {
            log.error("库存服务查询异常,原因：{}",e);
            throw new RRException(BizCodeEnum.NO_STOCK_EXCEPTION.getMsg(),BizCodeEnum.NO_STOCK_EXCEPTION.getCode());
        }


        //2、封装每个sku信息
        List<SkuEsModel.Attrs> finalAttrList = attrList;
        Map<Long, Boolean> finalStockMap = stockMap;
        List<SkuEsModel> upProduct = skuInfoEntityList.stream().map(sku -> {
            //组装需要的数据
            SkuEsModel esModel = new SkuEsModel();
            BeanUtils.copyProperties(sku, esModel);
            esModel.setSkuPrice(sku.getPrice());
            esModel.setSkuImg(sku.getSkuDefaultImg());
            //1、TODO 发送远程调用，是否有库存
            if (CollectionUtils.isEmpty(finalStockMap)) {
                esModel.setHasStock(true);
            } else {
                esModel.setHasStock(finalStockMap.get(sku.getSkuId()));
            }
            //2、TODO 热度评分 - 0
            esModel.setHotScore(0L);
            //3、TODO 查询品牌和分类信息
            BrandEntity brandEntity = brandService.getById(esModel.getBrandId());
            esModel.setBrandId(brandEntity.getBrandId());
            esModel.setBrandImg(brandEntity.getLogo());

            CategoryEntity categoryEntity = categoryService.getById(esModel.getCatelogId());
            // TODO 有空指针异常
            esModel.setCatelogName(categoryEntity.getName());

            //设置检索属性
            esModel.setAttrs(finalAttrList);

            return esModel;
        }).collect(Collectors.toList());

        //4、 将数据保存ES
        R r = searchFeignService.productUp(upProduct);
        if (r.getCode() == 0) {
            //远程调用成功
            //5、 修改商品发布状态已上架
            baseMapper.updateSpuStatus(spuId, ProductConstant.StatusEnum.SPU_UP.getCode());
        } else {
            //远程调用失败
            //TODO 重复调用，接口幂等行-重试机制
        }
    }
}
